import {GLTFExporter} from 'three/examples/jsm/exporters/GLTFExporter.js'
import {Matrix4, Quaternion} from 'three'

/**
 * 响应式画布 / 响应式three.js
 * @param renderer
 * @param camera
 * @param width
 * @param height
 */
export function canvasResize({renderer, composer, effectFXAA, camera, width, height}) {
  if (camera.type === 'PerspectiveCamera') {
    camera.aspect = width / height
  } else if (camera.type === 'OrthographicCamera') {
    camera.left = -width
    camera.right = width
    camera.top = height
    camera.bottom = -height
  }
  camera.updateProjectionMatrix()
  if (composer) {
    composer.setSize(width, height)
    effectFXAA.uniforms.resolution.value.set(1 / width, 1 / height)
  } else {
    renderer.setSize(width, height, false)
  }
}

/**
 * 节流
 * @param method
 * @param time
 * @returns {(function(...[*]=): void)|*}
 */
export function throttle(method, time) {
  time = time || 100
  let timeout
  let previous = 0
  return function (...args) {
    let context = this
    let now = new Date().getTime()
    let remaining = time - (now - previous)
    if (remaining <= 0 || remaining > time) {
      if (timeout) {
        clearTimeout(timeout)
        timeout = null
      }
      previous = now
      method.apply(context, args)
    } else if (!timeout) {
      timeout = setTimeout(() => {
        previous = new Date().getTime()
        timeout = null
        method.apply(context, args)
      }, remaining)
    }
  }
}

/**
 * 无限debug
 */
export function infinityDebug() {
  (function (a) {
    return (function (a) {
      return Function('Function(arguments[0]+"' + a + '")()')
    })(a)
  })('bugger')('de', 0, 0, (0, 0))
}

/**
 * 导出glb模型
 * @param scene
 * @param fileName
 */
export function gltfExporter(scene, fileName) {
  const exporter = new GLTFExporter()
  const animations = getAnimations(scene)
  exporter.parse(scene, function (result) {
    download(fileName, new Blob([result], {type: 'application/octet-stream'}))
  }, {binary: true, animations})
}


/**
 * 获取动画
 * @param scene
 * @returns {*[]}
 */
export function getAnimations(scene) {
  const animations = []
  scene.traverse(object => animations.push(...object.animations))
  return animations
}

/**
 * 下载文件
 * @param filename
 * @param content
 * @param contentType
 */
export function download(filename, content, contentType) {
  if (!contentType) contentType = 'application/octet-stream'
  let a = document.createElement('a')
  let blob
  Object.prototype.toString.call(content) === '[object String]' ?
    blob = new Blob([content], {'type': contentType}) : blob = content
  a.href = window.URL.createObjectURL(blob)
  a.download = filename
  a.click()
}


/**
 * 控制相机看向指定坐标
 */
export class RotationCamera {
  constructor(cameraToBeControl) {

    this.camera = cameraToBeControl
    this.rotationMatrix = new Matrix4()
    this.targetQuaternion = new Quaternion()
    this.speed = .02
    this.isRunning = false
    this.onComplete = null

    this.update = () => {

      if (!this.camera.quaternion.equals(this.targetQuaternion)) {

        this.isRunning = true
        this.camera.quaternion.rotateTowards(this.targetQuaternion, this.speed)
        requestAnimationFrame(this.update)

      } else {

        this._onComplete()

      }

    }

    this.setWorldPosition = (worldPosition, run = true) => {

      this.rotationMatrix.lookAt(worldPosition.clone().negate(), this.camera.position, this.camera.up)
      this.targetQuaternion.setFromRotationMatrix(this.rotationMatrix)
      if (run && !this.isRunning) this.update()
      return this.targetQuaternion

    }

    this._onComplete = () => {

      this.isRunning = false
      if (this.onComplete) this.onComplete()
    }
  }
}
